<?php

class DBService {
	
	var $mapping = array();
	
	var $XMLmapping;
	
	var $STRINGS = array('char', 'varchar', 'tinytext', 'text', 'blob', 'mediumtext', 'mediumblob', 'longtext', 'longblob', 'datetime', 'date', 'timestamp', 'time');

	var $NUMERIC = array('tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'decimal');
	
	function DBService($mapping = null){
		$mapping = isset($mapping) ? $mapping : DB_MAPPING;
		$this->XMLmapping = MappingService::getMapping($mapping); 
		$this->initMapping();
	}
	
	function populateModels($model){
		$resultArray = array();
		$mapping = $this->getMappingModel(get_class($model));		
		$query =  $this->buildSelectQuery($model, $mapping);		
		$res = $this->executeQuery($query);
				
		for($i = 0; $i < count($res); $i++){
			$result = new $mapping->className();			
			for($j = 0; $j < count($mapping->mapping); $j++){				
				call_user_func_array(array(&$result, 'set' . $mapping->mapping[$j]['objAttribute']), $res[$i][$mapping->mapping[$j]['tblField']]);
			}		
			$resultArray[$i] = $result;
		}
		return $resultArray;
	}
		
	function storeModel($model){
		$mapping = $this->getMappingModel(get_class($model));
		$query = $this->buildInsertQuery($model, $mapping);
		$this->executeQuery($query);		
	}	
	
	function initMapping(){			
		
		while($element = next($this->XMLmapping)){
			if($element['tag'] == 'MODEL' && isset($element['attributes'])){
				$bmm = new BaseMappingModel();
				$bmm->className = $element['attributes']['CLASS'];
				break;				
			}
		}

		if(isset($bmm) && $element){
		//searching for fieldset mapping name				
			while(($element = next($this->XMLmapping)) && $element['tag'] != 'MODEL'){
				if($element['tag'] == 'FIELDSET' && isset($element['attributes'])){
					$bmm->tableName = $element['attributes']['NAME'];
					break;
				}				
			}
			if($bmm->tableName != ''){				
				while(($element = next($this->XMLmapping)) && $element['tag'] != 'MODEL'){
					if($element['tag'] == 'FIELD' && isset($element['attributes'])){
						$objAttribute = $element['attributes']['ATTRIBUTE'];
						$objValue = null;
						$tblField = $element['attributes']['NAME'];
						$tblFieldType = $element['attributes']['TYPE']; 
						$tblFieldValue = null;
						$bmm->mapping[count($bmm->mapping)] = array('objAttribute' => $objAttribute, 'objValue' => $objValue, 'tblField' => $tblField, 'tblFieldType' => $tblFieldType, 'tblFieldValue' => $tblFieldValue);				
					}
				}
				$this->mapping[count($this->mapping)] = $bmm;								
			} 		
		} 		
		
		if($element){
			$this->initMapping();
		}		
	}
	
	function buildInsertQuery ($model, $mapping) {
		$query = 'insert into ';		
		$values = get_object_vars($model);
		$query .= $mapping->tableName . ' ';		
		$part1 = '('; 
		$part2 = ' values (';		
		for($i = 0; $i < count($mapping->mapping) - 1; $i++){
			$part1 .= $mapping->mapping[$i]['tblField'] . ', ';	
			$part2 .= $this->prepareValue($values[$mapping->mapping[$i]['objAttribute']], $mapping->mapping[$i]['tblFieldType']) . ', ';
		}
		$last = end($mapping->mapping);
		$part1 .= $last['tblField'] . ')';
		$part2 .= $this->prepareValue($values[$last['objAttribute']], $last['tblFieldType']) . ')';
		$query .= $part1 . $part2;  
		return $query;
	}
	
	function buildSelectQuery($model, $mapping){
		$query = 'select ';
		$mapping = $this->getMappingModel(get_class($model));
		$values = get_object_vars($model);
		$part1 = ''; 
		$part2 = '';
		$criteria = '';
		$count = 0;
		for($i = 0; $i < count($mapping->mapping) - 1; $i++){
			$part1 .= $mapping->mapping[$i]['tblField'] . ', ';
			$criteria = $values[$mapping->mapping[$i]['objAttribute']];
			if(isset($criteria) && $criteria != ''){
				if($count > 0){
					$part2 .= ' and ';
				} else {
					$part2 .= ' where ';
				}
				$part2 .= $mapping->mapping[$i]['tblField'] . '=' . $this->prepareValue($criteria, $mapping->mapping[$i]['tblFieldType']);
				$count++;
			}
		}		
		$element = end($mapping->mapping);
		$part1 .= $mapping->mapping[$i]['tblField'] . ' from ' . $mapping->tableName;
		if(isset($values[$element['objAttribute']]) && $values[$element['objAttribute']] != ''){
			if($count > 0){
					$part2 .= ' and ';
			} else {
					$part2 .= ' where ';
			}
			$part2 .= $element['tblField'] . "=" . $this->prepareValue($values[$element['objAttribute']], $element['tblFieldType']);
		}		
		$query .= $part1 . $part2;
		
		return $query;
	}
	
	function getMappingModel($modelClass){
		$result = null;
		for($i = 0; $i < count($this->mapping); $i++){
			if(strcasecmp($this->mapping[$i]->className, $modelClass) == 0){
				$result = $this->mapping[$i];
				break;
			}
		}
		return $result;
	}
	
	function prepareValue($value, $type){
		$size = null;		
		$expr = '/(^[^\(]+)\((\d+)\)$/';
		if(preg_match($expr, $type, $res) > 0){
			$type = $res[1];
			$size = $res[2];
		}
		
		if(in_array($type, $this->STRINGS)){
			if(isset($size) && strlen($value) > $size){
				$value = substr($value, 0, $size);
			}
			$value = '"' . mysql_escape_string($value) . '"';
		}
		return $value; 		
	}
	
	function executeQuery($query){
		$result = array();
		$settings = &getService('GlobalSettings');		
		$link = mysql_connect($settings->get('db_host'), $settings->get('db_username'), $settings->get('db_password'));
		mysql_select_db($settings->get('db_name'), $link) or die(mysql_error());		
		$res = mysql_query($query) or die(mysql_error() . '<br/> Query: ' . $query);
				
		if(isset($res) && $res != 1){
			while($row = mysql_fetch_array($res)){
				$result[count($result)] = $row; 			
			}
		}
		mysql_close($link);
		return $result;
	}

	
}
?>